/* 
 * Copyright IBM Japan, AMS Services 2004 ALL Rights Reserved.
 * 
 * This product includes software developed by 
 * the Apache Software Foundation (http://www.apache.org/).
 */
package com.tianqu.tms.core.mail;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.util.Date;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;

import com.tianqu.tms.core.base.Logger;
import com.tianqu.tms.core.util.Registry;
import com.tianqu.tms.core.util.TmsConstants;

/**
 * <p>mail锟斤拷锟脚达拷锟斤拷幕锟斤拷锟�/p><br />
 * 锟结供mail锟斤拷锟脚的癸拷同锟斤拷锟斤拷<br />
 * <br />
 * @author liugang
 *
 */
public abstract class MailSender implements TmsConstants{
	private Logger logger = Logger.getLogger(MailSender.class);

	/**
	 * 锟斤拷始锟斤拷系统锟斤拷锟斤拷锟侥硷拷指锟斤拷锟斤拷实锟斤拷锟斤拷<br />
	 * @return
	 */
	public static MailSender getInstance() {
		return (MailSender)Registry.get(MAIL_SENDER);
	}

	/**
	 * <p>锟斤拷锟脚的达拷锟�锟斤拷</p><br />
	 * 
	 * @param mailBean
	 * @throws Exception
	 */
	public abstract void sendMail(String From, String to, String cc, String funcId, Object mailinfoObject) throws Exception;


	/**
	 * <p>锟斤拷锟絤ail锟斤拷session</p><br />
	 * 
	 * @param keyName
	 * @return Session 
	 * @throws Exception
	 */
	protected abstract Session getSession(String keyName) throws Exception;


	/**
	 * <p>锟斤拷锟斤拷</p><br />
	 * 锟斤拷锟斤拷锟竭硷拷锟斤拷<br />
	 * 1. 取锟斤拷锟斤拷锟斤拷锟矫碉拷session<br />
	 * 2. mail锟斤拷锟斤拷锟斤拷锟斤拷锟�br />
	 * 3. 锟斤拷锟斤拷
	 *
	 * @param keyName
	 * @param mailBean 
	 * @throws MessagingException 
	 * @throws UnsupportedEncodingException 
	 * @throws Exception 
	 */
	protected synchronized void send(String keyName, MailBean mailBean)
		throws MessagingException, UnsupportedEncodingException, Exception {
		//print out log
		logger.debug("send was called.");

		Session session = null;
		MimeMessage message = null;

		try {
			session = getSession(keyName);
			message = createMessage(session);
			editMessage(session, message, mailBean);
			Transport.send(message);			

		} finally {
			session.getProperties().remove(MailConstants.MAIL_SMTP_FROM_KEY);
		}
	}

	/**
	 * @param session
	 * @return
	 */
	protected MimeMessage createMessage(Session session) {
		return new MimeMessage(session);
	}

	/**
	 * 
	 * @param session
	 * @param message
	 * @param mailBean
	 * @throws MessagingException
	 * @throws UnsupportedEncodingException
	 */
	protected void editMessage(
		Session session,
		MimeMessage message,
		MailBean mailBean)
		throws MessagingException, UnsupportedEncodingException {		
		// 锟斤拷锟絤essage锟斤拷头	
		setHeaders(message, mailBean.getFrom(), mailBean.getTo());

		// 锟斤拷锟絚c锟斤拷址锟斤拷
		setCc(message, mailBean.getCc());

		// 锟斤拷锟絙cc锟斤拷址
		setBcc(message, mailBean.getBcc());

		// 锟斤拷锟絩eply-to锟斤拷址
		setReplyTo(message, mailBean.getReplyTo());

		// 锟斤拷锟斤拷诺谋锟斤拷锟�
		setSubject(message, mailBean.getSubject());

		// 锟斤拷锟斤拷碌锟斤拷锟斤拷锟�
		setContent(message,mailBean.getText(),
				mailBean.getAttachmentFile(),
				mailBean.getAttachmentText(),
				mailBean.getAttachmentBytes());

		// 指锟斤拷锟斤拷锟脚碉拷址
		InternetAddress adderess = mailBean.getEnvelopeFrom();
		if (adderess == null) {
			adderess = mailBean.getFrom();
		}
		session.getProperties().put(
			MailConstants.MAIL_SMTP_FROM_KEY,
			adderess);
		message.saveChanges();

	}

	/**
	 * <p>锟斤拷锟絤essage锟斤拷头锟斤拷息
	 * message锟斤拷头锟斤拷息锟斤拷锟斤拷锟斤拷<br />
	 * 1. 锟斤拷锟脚碉拷址锟斤拷From锟斤拷<br />
	 * 2. 锟斤拷锟脚碉拷址锟斤拷To锟斤拷<br />
	 * 3. x-mailer锟斤拷锟斤拷锟斤拷<br />
	 * 4. 锟斤拷锟脚碉拷锟斤拷锟斤拷
	 * 
	 * @param message
	 * @param from 
	 * @param to
	 * @throws MessagingException 
	 */
	protected void setHeaders(
		MimeMessage message,
		InternetAddress from,
		InternetAddress[] to)
		throws MessagingException {

		message.setFrom(from);
		message.setRecipients(MimeMessage.RecipientType.TO, to);
		message.setHeader(
			MailConstants.HEAD_X_MAILER_KEY,
			MailConstants.HEAD_X_MAILER);
		message.setSentDate(new Date());
	}

	/**
	 * <p>锟斤拷锟絚c锟斤拷息</p><br />
	 * cc list锟斤拷锟斤拷锟絥ull 锟酵诧拷锟斤拷锟斤拷
	 * 
	 * @param message 
	 * @param cc 
	 * @throws MessagingException 
	 */
	protected void setCc(MimeMessage message, InternetAddress[] cc)
		throws MessagingException {
		if (cc == null || cc.length < 1) {
			return;
		}
		message.setRecipients(MimeMessage.RecipientType.CC, cc);
	}

	/**
	 * <p>锟斤拷锟絙cc锟斤拷息</p><br />
	 * bcc list锟斤拷锟斤拷锟絥ull 锟酵诧拷锟斤拷锟斤拷
	 * 
	 * @param message 
	 * @param bcc 
	 * @throws MessagingException 
	 */
	protected void setBcc(MimeMessage message, InternetAddress[] bcc)
		throws MessagingException {

		if (bcc == null || bcc.length < 1) {
			return;
		}
		message.setRecipients(MimeMessage.RecipientType.BCC, bcc);
	}

	/**
	 * <p>锟斤拷锟絩eply to锟斤拷息</p><br />
	 * replyto list锟斤拷锟斤拷锟絥ull 锟酵诧拷锟斤拷锟斤拷
	 * 
	 * @param message 
	 * @param reply to 
	 * @throws MessagingException 
	 */
	protected void setReplyTo(MimeMessage message, InternetAddress[] replyTo)
		throws MessagingException {
		if (replyTo == null || replyTo.length < 1) {
			return;
		}
		message.setReplyTo(replyTo);
	}

	/**
	 * 锟斤拷颖锟斤拷锟�
	 * @param message
	 * @param subject
	 * @throws MessagingException
	 * @throws UnsupportedEncodingException
	 */
	protected void setSubject(MimeMessage message, String subject)
		throws MessagingException, UnsupportedEncodingException {
		message.setSubject(
			MimeUtility.encodeText(
				subject,
				MailConstants.MAIL_CHARACTER_SET,
				MailConstants.MAIL_ENCODING));
	}

	/**
	 * <p>锟斤拷锟斤拷锟斤拷锟�/p><br />
	 * 锟斤拷锟斤拷锟竭硷拷锟斤拷锟铰ｏ拷<br />
	 * 1. 锟斤拷锟絤ail锟斤拷锟斤拷锟斤拷<br />
	 * 2. 锟斤拷锟斤拷懈锟斤拷锟斤拷锟斤拷希锟斤拷锟接革拷锟斤拷<br />
	 * 
	 * @param message
	 * @param text 
	 * @param attachmentFile 锟斤拷锟斤拷锟斤拷Attachment File锟斤拷
	 * @param attachmentText 锟斤拷锟斤拷锟斤拷Attachment Text锟斤拷
	 * @param attachmentBytes 锟斤拷锟斤拷锟斤拷Attachment Bytes锟斤拷
	 * @throws MessagingException
	 * @throws UnsupportedEncodingException 
	 */
	protected void setContent(MimeMessage message,String text,File[] attachmentFile,
		AttachmentTextBean[] attachmentText,
		ByteArrayDataSource[] attachmentBytes)throws MessagingException, UnsupportedEncodingException {
		MimeMultipart content = new MimeMultipart();
		if ((attachmentFile == null || attachmentFile.length < 1)
			&& (attachmentText == null || attachmentText.length < 1)
			&& (attachmentBytes == null || attachmentBytes.length < 1)) {
			message.setText(text, MailConstants.MAIL_CHARACTER_SET);
			return;
		}
		message.setContent(content);
		setTextToContent(content, text);
		setAttachmentFileToContent(content, attachmentFile);
		setAttachmentTextToContent(content, attachmentText);
		setAttachmentBytesToContent(content, attachmentBytes);
	}

	/**
	 * <p>锟斤拷锟斤拷锟斤拷锟斤拷锟较�/p><br />
	 * 锟斤拷锟斤拷锟斤拷锟斤拷锟絥ull 锟酵诧拷锟斤拷锟斤拷
	 * @param content
	 * @param text 
	 * @throws MessagingException 
	 * @throws UnsupportedEncodingException 
	 */
	protected void setTextToContent(MimeMultipart content, String text)
		throws MessagingException, UnsupportedEncodingException {

		MimeBodyPart textPart = new MimeBodyPart();
		textPart.setText(text, MailConstants.MAIL_CHARACTER_SET);
		content.addBodyPart(textPart);
	}

	/**
	 * <p>锟斤拷痈锟斤拷锟斤拷锟紸ttachment File锟斤拷</p><br />
	 * 锟斤拷锟斤拷锟斤拷Attachment File锟斤拷锟角空就诧拷锟斤拷锟斤拷
	 * 
	 * @param content
	 * @param attachmentFile 
	 * @throws MessagingException 
	 * @throws UnsupportedEncodingException 
	 */
	protected void setAttachmentFileToContent(
		MimeMultipart content,
		File[] attachmentFile)
		throws MessagingException, UnsupportedEncodingException {

		if (attachmentFile == null || attachmentFile.length < 1) {
			return;
		}
		for (int i = 0; i < attachmentFile.length; i++) {
			FileDataSource dataSource = new FileDataSource(attachmentFile[i]);
			DataHandler dataHeader = new DataHandler(dataSource);
			MimeBodyPart attachmentPart = new MimeBodyPart();
			attachmentPart.setDataHandler(dataHeader);
			attachmentPart.setFileName(
				MimeUtility.encodeText(
					dataSource.getName(),
					MailConstants.MAIL_CHARACTER_SET,
					MailConstants.MAIL_ENCODING));
			content.addBodyPart(attachmentPart);
		}
	}

	/**
	 * <p>锟斤拷痈锟斤拷锟斤拷锟紸ttachment Text锟斤拷</p><br />
	 * 锟斤拷锟斤拷锟斤拷Attachment Text锟斤拷锟角空就诧拷锟斤拷锟斤拷
	 * 
	 * @param content 
	 * @param attachmentText 
	 * @throws MessagingException 
	 * @throws UnsupportedEncodingException 
	 */
	protected void setAttachmentTextToContent(
		MimeMultipart content,
		AttachmentTextBean[] attachmentText)
		throws MessagingException, UnsupportedEncodingException {

		if (attachmentText == null || attachmentText.length < 1) {
			return;
		}
		for (int i = 0; i < attachmentText.length; i++) {
			AttachmentTextBean bean = attachmentText[i];
			MimeBodyPart attachmentPart = new MimeBodyPart();
			attachmentPart.setText(bean.getText(), bean.getEncoding());
			attachmentPart.setFileName(
				MimeUtility.encodeText(
					bean.getFileName(),
					MailConstants.MAIL_CHARACTER_SET,
					MailConstants.MAIL_ENCODING));
			content.addBodyPart(attachmentPart);
		}
	}

	/**
	 * <p>锟斤拷痈锟斤拷锟斤拷锟紸ttachment Bytes锟斤拷</p><br />
	 * 锟斤拷锟斤拷锟斤拷Attachment Bytes锟斤拷锟角空就诧拷锟斤拷锟斤拷
	 * 
	 * @param content
	 * @param attachmentBytes 
	 * @throws MessagingException 
	 * @throws UnsupportedEncodingException 
	 */
	protected void setAttachmentBytesToContent(
		MimeMultipart content,
		ByteArrayDataSource[] attachmentBytes)
		throws MessagingException, UnsupportedEncodingException {

		if (attachmentBytes == null || attachmentBytes.length < 1) {
			return;
		}
		for (int i = 0; i < attachmentBytes.length; i++) {
			ByteArrayDataSource dataSource = attachmentBytes[i];
			DataHandler dataHeader = new DataHandler(dataSource);
			MimeBodyPart attachmentPart = new MimeBodyPart();
			attachmentPart.setDataHandler(dataHeader);
			attachmentPart.setFileName(
				MimeUtility.encodeText(
					dataSource.getName(),
					MailConstants.MAIL_CHARACTER_SET,
					MailConstants.MAIL_ENCODING));
			content.addBodyPart(attachmentPart);
		}
	}
}
